package online.heycm.rbac.common.utils;

import online.heycm.platform.common.entity.result.Optional;
import online.heycm.platform.redis.RedisCache;
import online.heycm.rbac.common.constant.Constant;
import online.heycm.rbac.common.constant.ErrorCode;
import online.heycm.rbac.common.entity.Session;
import org.springframework.util.StringUtils;

/**
 * @author heycm
 * @since 2024/1/20 17:22
 */
public class SessionUtil {

    private SessionUtil() {
    }

    /**
     * 获取token的key
     *
     * @param userId 用户ID
     * @return
     */
    private static String getTokenKey(int userId) {
        return String.format(Constant.LOGIN_KEY, userId);
    }

    /**
     * 获取session的key
     *
     * @param token token
     * @return
     */
    private static String getSessionKey(String token) {
        return String.format(Constant.SESSION_KEY, token);
    }

    /**
     * 保存session
     *
     * @param expire     过期时间
     * @param session    session
     * @param redisCache redis缓存
     * @return
     */
    public static Optional saveSession(long expire, Session session, RedisCache redisCache) {
        expire(session.getUserId(), redisCache);
        boolean ok = redisCache.hSetObject(getSessionKey(session.getToken()), session, expire);
        if (!ok) {
            return Optional.error(ErrorCode.SESSION_STORAGE);
        }
        ok = redisCache.set(getTokenKey(session.getUserId()), session.getToken(), expire);
        if (!ok) {
            return Optional.error(ErrorCode.SESSION_STORAGE);
        }
        return Optional.success();
    }

    /**
     * 过期session
     *
     * @param userId     用户ID
     * @param redisCache redis缓存
     * @return
     */
    public static Optional expire(int userId, RedisCache redisCache) {
        String token = redisCache.get(getTokenKey(userId));
        if (StringUtils.hasText(token)) {
            redisCache.del(getSessionKey(token));
            redisCache.del(getTokenKey(userId));
        }
        return Optional.success();
    }

    /**
     * 过期session
     *
     * @param session    session
     * @param redisCache redis缓存
     * @return
     */
    public static Optional expire(Session session, RedisCache redisCache) {
        redisCache.del(getSessionKey(session.getToken()));
        redisCache.del(getTokenKey(session.getUserId()));
        return Optional.success();
    }

    /**
     * 获取token
     *
     * @param userId     用户ID
     * @param redisCache redis缓存
     * @return
     */
    public static Optional<String> getToken(int userId, RedisCache redisCache) {
        String token = redisCache.get(getTokenKey(userId));
        if (StringUtils.isEmpty(token)) {
            return Optional.error(ErrorCode.SESSION_EXPIRE);
        }
        return Optional.of(token);
    }

    /**
     * 获取session
     *
     * @param token      token
     * @param redisCache redis缓存
     * @return
     */
    public static Optional<Session> getSession(String token, RedisCache redisCache) {
        Session session = redisCache.hGet(getSessionKey(token), Session.class);
        if (session == null) {
            return Optional.error(ErrorCode.SESSION_EXPIRE);
        }
        return Optional.of(session);
    }

    /**
     * 获取session
     *
     * @param userId     用户ID
     * @param redisCache redis缓存
     * @return
     */
    public static Optional<Session> getSession(int userId, RedisCache redisCache) {
        return getToken(userId, redisCache).flatMap(token -> getSession(token, redisCache));
    }

    /**
     * 更新session
     *
     * @param userId     用户ID
     * @param item       item
     * @param value      value
     * @param redisCache redis缓存
     * @return
     */
    public static Optional updateSession(int userId, String item, Object value, RedisCache redisCache) {
        Optional<Session> optional = getSession(userId, redisCache);
        if (optional.fail()) {
            return optional;
        }
        boolean ok = redisCache.hSet(getSessionKey(optional.get().getToken()), item, value);
        return ok ? Optional.success() : Optional.error(ErrorCode.SESSION_STORAGE);
    }

    /**
     * 更新session
     *
     * @param token      token
     * @param item       item
     * @param value      value
     * @param redisCache redis缓存
     * @return
     */
    public static Optional updateSession(String token, String item, Object value, RedisCache redisCache) {
        Optional<Session> optional = getSession(token, redisCache);
        if (optional.fail()) {
            return optional;
        }
        boolean ok = redisCache.hSet(getSessionKey(optional.get().getToken()), item, value);
        return ok ? Optional.success() : Optional.error(ErrorCode.SESSION_STORAGE);
    }

}
